<?php
namespace Tbf\Bundle\YntAuthBundle\Denglu;
use Guzzle\Http\Client;
use Guzzle\Http\Exception\ClientErrorResponseException;
use Guzzle\Http\Url;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Tbf\Bundle\CallbackSerializerBundle\CallbackSerializer;
use Tbf\Bundle\YntAuthBundle\MediaImpInterface;
use Tbf\Bundle\YntAuthBundle\Model\LoginRequest;
use Tbf\Bundle\SerializerBundle\Serializer;
use Tbf\Bundle\YntAuthBundle\Model\LoginResponse;
use Tbf\Bundle\YntAuthBundle\Model\ShareRequest;
use Tbf\Bundle\YntAuthBundle\Service\MediaManager;
use Tbf\Bundle\YntAuthBundle\Service\TransactionManager;
use Tbf\Component\Arrays\ArrayFunction;
use Tbf\Component\Crypto\CryptoRandUtil;
use Tbf\Component\Path\PathFunction;

class Denglu implements MediaImpInterface{
    /** @var \Tbf\Bundle\YntAuthBundle\Denglu\Config  */
    protected $config;
    /** @var \Guzzle\Http\Client  */
    protected $http;

    protected $transaction_manager;
    protected $serializer;
    function __construct(
            Config $config,
            Client $http,
            TransactionManager $transaction_manager,
            Serializer $serializer
        ){
        $this->config = $config;
        $this->http = $http;
        $this->transaction_manager = $transaction_manager;
        $this->serializer = $serializer;
    }

    function login(LoginRequest $request){
        $transaction = $this->transaction_manager->newTransaction();
        $transaction->setLoginCallback($request->getPageCallback());
        $transaction->setExtraData($request->getExtraData());
        $transaction->setMedia($request->getMedia());
        $this->transaction_manager->save($transaction);

        $url = PathFunction::urlJoin($this->config->getDengluUrlBase(),'transfer/'.$transaction->getMedia()->getNameEn());
        $url = Url::factory($url);
        $url->setQuery(array(
            'appid'=>$this->config->getAppKey(),
            'redirect_uri'=>$transaction->getId()   //denglu.cc只能用redirect_uri传递数据(居然未文档)
        ));
        return new RedirectResponse((string)$url);
    }
    function onToken(Request $request){
        $input = $request->query->all();
        $err = ArrayFunction::checkParameterExist($input,array('token','redirect_url'));
        if ($err!==null){
            return new Response($err);
        }
        $transaction_id = $input['redirect_url'];
        $transaction = $this->transaction_manager->get($transaction_id);
        if (empty($transaction)){
            return new Response('事务不存在');
        }
        $response = new LoginResponse();
        $response->setToken($input['token']);
        $transaction->setAccessToken($input['token']);
        $response->setMedia($transaction->getMedia());
        $response->setExtraData($transaction->getExtraData());
        if (!empty($input['mediaUserID'])){
            $response->setMediaUserID($input['mediaUserID']);
            $transaction->setMediaUserId($input['mediaUserID']);
        }
        $response->setTransactionId($transaction_id);
        $callback = $transaction->getLoginCallback();
        $this->transaction_manager->save($transaction);
        return $callback->invoke($response);
    }

    /**
     * @param string $transaction_id
     * @return \Tbf\Bundle\YntAuthBundle\Model\User|null
     */
    function getCurrentUserInfo($transaction_id){
        $transaction = $this->transaction_manager->get($transaction_id);
        if (empty($transaction)){
            return null;
        }
        $data = $this->apiCall('getUserInfo',array('token'=>$transaction->getAccessToken()));
        if (empty($data)){
            return null;
        }
        $user = $this->serializer->newFromArray('\Tbf\Bundle\YntAuthBundle\Model\User',$data);
        /** @var \Tbf\Bundle\YntAuthBundle\Model\User $user */
        $user->setMedia($transaction->getMedia());
        $transaction->setMediaUserId($user->getMediaUserID());
        $this->transaction_manager->save($transaction);
        return $user;
    }
    /**
     * 绑定帐号,一个奇葩功能...
     * @param array $input
     * @return err
     * struct{
     *  muid string //获取到的mediaUserID (必有)
     *  uid string //本站用户id(必有)
     *  uname string  //本站昵称(可选)
     *  uemail string //本站email(可选)
     * }
     */
    /*
    function bind($input){
        $err = ArrayFunction::checkParameterExist($input,array('muid','uid'));
        if ($err!==null){
            return $err;
        }
        $input = ArrayFunction::filterParameter($input,array('muid','uid',
            'uname','uemail'
        ));
        $data = $this->apiCall('bind',$input);
        if ($data['result']!=1){
            return 'api返回错误';
        }
        return null;
    }*/
    /**
     * 分享
     * @param array $input
     * @return err
     * struct{
     *  muid string //获取到的mediaUserID (必有)
     *  content string //分享内容(必有)
     *  url string  //查看信息的链接(必有)
     *  imageurl string //图片url(可选)
     *  videourl string //视频url(可选)
     *  uid string //网站用户的唯一性标识ID(可选)
     * }
     */
    function share(ShareRequest $share_request){
        $transaction = $this->transaction_manager->get($share_request->getTransactionId());
        if (empty($transaction)){
            return '事务不存在';
        }
        $data = $this->apiCall('share',array(
            'content'=>$share_request->getContent(),
            'muid'=>$transaction->getMediaUserId(),
            'url'=>$share_request->getUrl(),
            'imageurl'=>$share_request->getImageUrl(),
            'viedourl'=>$share_request->getVideoUrl(),
        ));
        if ($data['result']!=1){
            return 'api返回错误';
        }
        return null;
    }
    protected function apiCall($name,$input){
        $url = $this->config->getApiUrl($name);
        $input['appid'] = $this->config->getAppKey();
        $input['timestamp'] = time().'000';
        $input = DengluSign::signArray($input,$this->config->getAppSecret());
        $request = $this->http->post($url,null,$input);
        try{
            $response = $request->send();
        }catch(ClientErrorResponseException $e){
            $ret  = $e->getMessage()."\n";
            $ret .= '---------------------'."\n";
            $ret .= $e->getRequest()."\n";
            $ret .= '---------------------'."\n";
            $ret .= $e->getResponse()."\n";

            throw new \Exception($ret);
        }
        $output = json_decode($response->getBody(),true);
        return $output;
    }
    public function getName(){
        return 'denglu';
    }
}
